package com.cms.utils.generate;

import freemarker.template.Template;

import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 代码生成器
 */
@SuppressWarnings("unused")
public class CodeGenerateUtils {

    private final String AUTHOR = "yangtao";
    private final String CURRENT_DATE = "2018/04/17";
//    private final String tableName = "sys_dict";
    private final String packageName = "com.cms.model.vo";
//    private final String tableAnnotation = "系统用户表";
    private final String URL = "jdbc:mysql://localhost:3306/db_cms";
    private final String USER = "root";
    private final String PASSWORD = "kangshu";
    private final String DRIVER = "com.mysql.jdbc.Driver";
    private final String diskPath = "D://generate//";
    
    // 定义数据库的链接  
    private Connection connection;  
    
    // 表备注信息
    private String tableAnnotation;
    
    private String tableName;
    
    private String changeTableName;
  

    public Connection getConnection() throws Exception{
        Class.forName(DRIVER);
        connection= DriverManager.getConnection(URL,USER,PASSWORD);
        return connection;
    }

    public static void main(String[] args) throws Exception{
        CodeGenerateUtils codeGenerateUtils = new CodeGenerateUtils();
        codeGenerateUtils.generate();
    }

    public void generate() throws Exception{
        try {
            connection = getConnection();
            DatabaseMetaData meta = connection.getMetaData();
            ResultSet rsult = meta.getTables(null, null, "%", null);
            List<String> list = new ArrayList<String>();
            while(rsult.next()){
              tableName = rsult.getString("TABLE_NAME");
              tableAnnotation = rsult.getString("REMARKS");
              changeTableName = replaceUnderLineAndUpperCase(tableName);
              ResultSet resultSet = meta.getColumns(null,"%",rsult.getString("TABLE_NAME"),"%");
              //生成Model文件
              generateModelFile(resultSet);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally{

        }
    }

    //生成Model文件
    private void generateModelFile(ResultSet resultSet) throws Exception{
        final String suffix = ".java";
        final String path = diskPath + changeTableName + suffix;
        final String templateName = "model.ftl";
        File mapperFile = new File(path);
        List<ColumnClass> columnClassList = new ArrayList<>();
        ColumnClass columnClass = null;
        while(resultSet.next()){
            //id字段略过
            if(resultSet.getString("COLUMN_NAME").equals("id")) continue;
            columnClass = new ColumnClass();
            //获取字段名称
            columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));
            //获取字段类型
            columnClass.setColumnType(resultSet.getString("TYPE_NAME").toLowerCase());
            //转换字段名称，如 sys_name 变成 SysName
            columnClass.setChangeColumnName(replaceUnderLineAndUpperCase(resultSet.getString("COLUMN_NAME")));
            //字段在数据库的注释
            columnClass.setColumnComment(resultSet.getString("REMARKS"));
            columnClassList.add(columnClass);
        }
        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("model_column",columnClassList);
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }
    
    //生成Mapper文件
	private void generateMapperFile(ResultSet resultSet) throws Exception{
        final String suffix = "Mapper.xml";
        final String path = diskPath + changeTableName + suffix;
        final String templateName = "Mapper.ftl";
        File mapperFile = new File(path);
        Map<String,Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }

    //生成Dao文件
    private void generateDaoFile(ResultSet resultSet) throws Exception{
        final String suffix = "Dao.java";
        final String path = diskPath + changeTableName + suffix;
        final String templateName = "Dao.ftl";
        File mapperFile = new File(path);
        Map<String,Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }
    
    //生成服务层接口文件
    private void generateIServiceFile(ResultSet resultSet) throws Exception{
        final String prefix = "I";
        final String suffix = "Service.java";
        final String path = diskPath + prefix + changeTableName + suffix;
        final String templateName = "IService.ftl";
        File mapperFile = new File(path);
        Map<String,Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }
    
    //生成服务实现层文件
    private void generateServiceFile(ResultSet resultSet) throws Exception{
        final String suffix = "Service.java";
        final String path = diskPath + changeTableName + suffix;
        final String templateName = "Service.ftl";
        File mapperFile = new File(path);
        Map<String,Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }
    
    //生成Controller层文件
    private void generateControllerFile(ResultSet resultSet) throws Exception{
        final String suffix = "Controller.java";
        final String path = diskPath + changeTableName + suffix;
        final String templateName = "Controller.ftl";
        File mapperFile = new File(path);
        Map<String,Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName,mapperFile,dataMap);
    }


    private void generateFileByTemplate(final String templateName,File file,Map<String,Object> dataMap) throws Exception{
        Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
        FileOutputStream fos = new FileOutputStream(file);
        dataMap.put("table_name",tableName);
        dataMap.put("table_name_max",changeTableName);
        dataMap.put("table_name_min",changeTableName.substring(0,1).toLowerCase() + changeTableName.substring(1));
        dataMap.put("author",AUTHOR);
        dataMap.put("date",CURRENT_DATE);
        dataMap.put("package_name",packageName);
        dataMap.put("table_annotation",tableAnnotation);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);
        template.process(dataMap,out);
    }

    public String replaceUnderLineAndUpperCase(String str){
        StringBuffer sb = new StringBuffer();
        sb.append(str);
        int count = sb.indexOf("_");
        while(count!=0){
            int num = sb.indexOf("_",count);
            count = num + 1;
            if(num != -1){
                char ss = sb.charAt(count);
                char ia = (char) (ss - 32);
                sb.replace(count , count + 1,ia + "");
            }
        }
        String result = sb.toString().replaceAll("_","");
        return StringUtils.capitalize(result);
    }

}
